package com.lishem.carl._10dp;


/**
 * https://leetcode.cn/problems/integer-break/description/
 * 给定一个正整数 n ，将其拆分为 k 个 正整数 的和（ k >= 2 ），
 * <p>
 * 并使这些整数的乘积最大化。
 * <p>
 * 返回 你可以获得的最大乘积 。
 * <p>
 * 本题主要是需要想到  一个数拆分，如果要和前面的子问题产生联系，需要将其分解为
 * <p>
 * 拆成2份  和 拆成多份   拆成两份
 * <p>
 * 1. 确定dp数组（dp table）以及下标的含义
 * <p>
 * 第 i 位置上拆分能得到的最大值
 * <p>
 * 2. 确定递推公式
 * <p>
 * dp[i] =  for i in 1~i-1  max( max ( j*(i-j) , j*dp[i-j]  )) ;
 * <p>
 * 3. dp数组如何初始化
 * <p>
 * dp[2] = 1
 * <p>
 * 4. 确定遍历顺序
 * <p>
 * 从前往后
 * <p>
 * 5. 举例推导dp数组
 */
public class _6LetCode343_整数拆分 {

    /**
     * 动态规划
     */
    public int integerBreak2(int n) {
        int[] dp = new int[n + 1];
        dp[2] = 1;
        for (int i = 3; i < dp.length; i++) {
            int max = Integer.MIN_VALUE;
            for (int j = 1; j < i; j++) {
                max = Math.max(max, j * (i - j));
                max = Math.max(max, j * dp[i - j]);
            }
            dp[i] = max;
        }
        return dp[n];
    }

    /**
     * 贪心法，找规律
     */
    public int integerBreak1(int n) {
        if (n == 2) {
            return 1;
        }
        if (n == 3) {
            return 2;
        }
        if (n == 4) {
            return 4;
        }
        int pow = n / 3;
        int yushu = n % 3;
        if (yushu == 1) {
            pow--;
            yushu = 4;
        }
        int res = 1;
        for (int i = 0; i < pow; i++) {
            res *= 3;
        }
        return res * (yushu == 0 ? 1 : yushu);
    }

    public static void main(String[] args) {
        _6LetCode343_整数拆分 sol = new _6LetCode343_整数拆分();
        for (int i = 2; i < 20; i++) {
            System.out.println(i + "---" + sol.integerBreak1(i));
            System.out.println(i + "---" + sol.integerBreak2(i));
        }
    }
}
